package org.candan.spider.task.spider.ftp;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.DecimalFormat;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.log4j.Logger;
import org.candan.spider.bean.DataSift;
import org.candan.spider.bean.Plan;
import org.candan.spider.bean.TagSift;
import org.candan.spider.task.spider.SpiderPlan;
import org.candan.spider.util.DateUtil;
import org.candan.spider.util.SLog;



public class FtpDownload extends SpiderPlan{
	public FtpDownload(Plan plan) {
		super(plan);
	}
	public FtpDownload(Plan plan,DataSift dst, TagSift tsf){
		super(plan,dst,tsf);
	}
	private FTPClient ftpClient = new FTPClient();   
	private Logger logger = new SLog("FtpDownload").getLogger();
	private int conNum = 1;
	
	@Override
	protected void execueSpiderPlan(String url, String output){
		connect(url, output);
	}
	public boolean connect(String ftp, String localDir){
		String[] str = ftp.replace("ftp://", "").split("/");
		String hostname = str[0];
		int port = 21;
		String username = "anonymous";
		String password = "12@download";
		
		localDir = localDir.endsWith("/")? localDir : localDir+"/";
		String remote ="/";
		for(int i = 1; i < str.length; i++){
			remote += str[i] + "/";
		}

		try {
			logger.info("建立ftp连接:"+ftp);
			//连接到FTP服务器 
			boolean isConnect = connect(hostname, port, username, password);
			System.out.println(isConnect);
			//远程文件下载到本地
			download(remote, localDir);
			disconnect();   
			logger.info("  断开ftp连接:"+ftp);
		  } catch (IOException e) {
			  e.printStackTrace();
			  System.err.println(conNum);
			  //如果连接失败，有20次的尝试机会
			  if(++conNum <=20){
				  logger.error("连接FTP出错："+e.getMessage()+"; 进入第" + conNum+" 次连接！共尝试 20 次连接");
				  try {
					Thread.sleep(2000);
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
//				  logger.
				  return connect(ftp, localDir);
			  }else{
//		          e.printStackTrace();
				  logger.error("连接FTP失败："+ftp);
		          conNum = 1;
		          return false;
			  }
		  }
//		  conNum = 1;
		return true;
	}
	/** 
     * 连接到FTP服务器 
     * @param hostname 主机名 
     * @param port 端口 
     * @param username 用户名 
     * @param password 密码 
     * @return 是否连接成功 
     * @throws IOException 
     */ 
    public boolean connect(String hostname,int port,String username,String password) throws IOException{   
    	logger.info(hostname +" , "+port+" , "+username+" , "+password);
        ftpClient.connect(hostname, port);
        ftpClient.setControlEncoding("GBK");   
        if(FTPReply.isPositiveCompletion(ftpClient.getReplyCode())){   
            if(ftpClient.login(username, password)){   
                return true;   
            }   
        }   
//        disconnect();   
        return false;   
    }   
   
    /** 
     * 断开与远程服务器的连接 
     * @throws IOException 
     */ 
    public void disconnect() throws IOException{   
        if(ftpClient.isConnected()){   
            ftpClient.disconnect();   
        }   
    }  
    
    /** 
     * 从FTP服务器上下载文件,支持断点续传，上传百分比汇报 
     * @param remote 远程文件路径 
     * @param local 本地文件路径 
     * @return 上传的状态 
     * @throws IOException 
     */ 
    public void download(String remote,String local) throws IOException{  
    	System.out.println("in download ");
        //设置被动模式   
        ftpClient.enterLocalPassiveMode();   
        //设置以二进制方式传输   
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);   
        //检查远程文件是否存在   
        System.out.println(remote);
        FTPFile[] files = ftpClient.listFiles(new String(remote.getBytes("GBK"),"iso-8859-1"));  
        for(int i = 0; i < files.length; i++){
        	if(!dataFilterDownNumCheck())break;
        	if(!dataFilterBasicCheck(files[i].getName()))continue;
        	downloadFile(files[i], remote, local);
        }
    }   

    private void downloadFile(FTPFile remoteFile,String remoteDir, String local) {
//        if(!remoteFile.getName().contains("20110116"))return null;
        File f = new File(local + remoteFile.getName());   
        if(!lockFile(f)){
        	return ;
        }
        try {
        long lRemoteSize = remoteFile.getSize(); 
        long localSize = 0L;
        int c; 
        long process=0; 
        long nowProcess;
        boolean upStatus;
        String fileSize = DateUtil.getNumFmat(lRemoteSize/1000.0)+"KB";
        //判断本地文件大小是否大于远程文件大小   
//        if(f.exists() && (localSize=f.length()) >= lRemoteSize){   
////            logger.warn("本地文件大于远程文件，下载中止");   
//            return DownloadStatus.Local_Bigger_Remote;   
//        }  
        if(isExistWholeFile(f,lRemoteSize)){
        	return ;
        }
        logger.info("==开始下载："+remoteFile.getName()+ "  , "+fileSize );
    	if(f.exists()){   
             
            //进行断点续传，并记录状态   
            FileOutputStream out = new FileOutputStream(f,true);   
            ftpClient.setRestartOffset(localSize);   
			InputStream in = ftpClient.retrieveFileStream(new String((remoteDir+remoteFile.getName()).getBytes("GBK"),"iso-8859-1"));
			localSize=f.length();
            byte[] bytes = new byte[1024];   
            long step = lRemoteSize /100;   
            process=localSize /step;   
            while((c = in.read(bytes))!= -1){   
                out.write(bytes,0,c);   
                localSize+=c;   
                nowProcess = localSize /step;   
                if(nowProcess > process){   
                    process = nowProcess;   
                    if(process % 10 == 0){
                    	logger.info("    "+f.getName()+":下载进度："+process+"%");   
                    }
                    //TODO 更新文件下载进度,值存放在process变量中   
                }   
            }   
            in.close();
            out.close();
            upStatus = ftpClient.completePendingCommand();   
            if(!upStatus){   
                logger.info("下载失败");
            }   
        }else {   
        	f.createNewFile();
            OutputStream out = new FileOutputStream(f);   
            InputStream in= ftpClient.retrieveFileStream(new String((remoteDir+remoteFile.getName()).getBytes("GBK"),"iso-8859-1"));   
            byte[] bytes = new byte[1024];   
            long step = lRemoteSize /100;   
            while((c = in.read(bytes))!= -1){   
                out.write(bytes, 0, c);   
                localSize+=c;   
                nowProcess = localSize /step;   
                if(nowProcess > process){   
                    process = nowProcess;   
                    if(process % 10 == 0){ 
                    	logger.info("    "+f.getName()+":下载进度："+process+"%");
                    }
                    // 更新文件下载进度,值存放在process变量中   
                }   
            }   
            in.close();   
            out.close();   
            upStatus= ftpClient.completePendingCommand();   
            if(!upStatus){   
                logger.info("下载失败");
            }   
        }
    	if(upStatus){
    		addResult(remoteFile.getName(), fileSize, f.getAbsolutePath());
    	}
    	 logger.info("==完成下载："+remoteFile.getName());
        }  catch (IOException e) {
        	// TODO Auto-generated catch block
        	e.printStackTrace();
        }finally{
        	 releaseLock(f);
        }
    }
    
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		FtpDownload myFtp = new FtpDownload(null,null,null);   
		myFtp.connect("ftp://205.167.25.154/san1/oisst/NetCDF/2011/AVHRR/","e:/temp/delete2");   
		
		 DecimalFormat df1 = new DecimalFormat("#,###,###.###"); 
         System.out.println(df1.format(234234.234634)); 
         System.out.println(df1.format(34.234634)); 
         System.out.println(df1.format(34234634)); 
	}

}
